/*            Copyright(c) 2006-2008 Dave Sexton           *
 * http://www.codeplex.com/DocProject                      *
 * http://www.codeplex.com/DocProject/Project/License.aspx *
 ***********************************************************/
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace DaveSexton.DocProject.Sandcastle
{
	public sealed partial class MissingDependenciesEditorDialog : Form
	{
		#region Public Properties
		public bool HasChanges
		{
			get
			{
				return hasChanges;
			}
		}

		public IEnumerable<SystemPath> Dependencies
		{
			get
			{
				List<SystemPath> dependencies = new List<SystemPath>();

				foreach (DataGridViewRow row in dependenciesDataGridView.Rows)
				{
					if (row.IsNewRow)
						continue;

					string dependency = (string) row.Cells[dependencyColumn.DisplayIndex].Value;

					if (!string.IsNullOrEmpty(dependency))
						dependencies.Add(new SystemPath(project.Directory, dependency, true));
				}

				return dependencies.AsReadOnly();
			}
		}
		#endregion

		#region Private / Protected
		private bool hasChanges;
		private readonly IDocProject project;
		#endregion

		#region Constructors
		/// <summary>
		/// Constructs a new instance of the <see cref="MissingDependenciesEditorDialog" /> class.
		/// </summary>
		public MissingDependenciesEditorDialog(IEnumerable<SystemPath> dependencies, IDocProject project)
			: this()
		{
			if (project == null)
				throw new ArgumentNullException("project");

			this.project = project;

			this.Text = project.Name + " - " + this.Text;

			foreach (SystemPath dependency in dependencies)
				dependenciesDataGridView.Rows.Add(dependency.CompleteRelativeTo(project.Directory));

			dependencyColumn.InitializeFileDialog += fileColumn_InitializeFileDialog;
			dependencyColumn.InitializeFolderDialog += fileColumn_InitializeFolderDialog;
		}

		/// <summary>
		/// Constructs a new instance of the <see cref="MissingDependenciesEditorDialog" /> class.
		/// </summary>
		private MissingDependenciesEditorDialog()
		{
			InitializeComponent();
		}
		#endregion

		#region Methods
		private bool ValidateCell(DataGridViewCell cell)
		{
			string value = (string) cell.FormattedValue;

			if (string.IsNullOrEmpty(value) || !PathFormat.IsValid(value, false))
			{
				errors.SetError(okButton, Resources.Text.InvalidPath);
				return false;
			}

			return true;
		}
		#endregion

		#region Event Handlers
		protected override void OnValidating(CancelEventArgs e)
		{
			foreach (DataGridViewRow row in this.dependenciesDataGridView.Rows)
			{
				if (!ValidateCell(row.Cells[dependencyColumn.DisplayIndex]))
					e.Cancel = true;
			}

			if (!e.Cancel)
				errors.SetError(okButton, null);

			base.OnValidating(e);
		}

		private void fileColumn_InitializeFileDialog(object sender, DataGridViewFileColumnDialogEventArgs e)
		{
			e.Dialog.CheckFileExists = true;
			e.Dialog.Filter = Resources.Text.AssemblyDialogFilter;
			e.Dialog.Title = "Select an assembly";
		}

		private void fileColumn_InitializeFolderDialog(object sender, DataGridViewFileColumnFolderDialogEventArgs e)
		{
			e.Dialog.Description = "Select a folder that contains dependent assemblies";
		}

		private void okButton_Click(object sender, EventArgs e)
		{
			if (Validate(false))
				DialogResult = DialogResult.OK;
		}

		private void dependenciesDataGridView_UserAddedRow(object sender, DataGridViewRowEventArgs e)
		{
			hasChanges = true;
		}

		private void dependenciesDataGridView_UserDeletedRow(object sender, DataGridViewRowEventArgs e)
		{
			hasChanges = true;
		}

		private void dependenciesDataGridView_CellValueChanged(object sender, DataGridViewCellEventArgs e)
		{
			if (e.RowIndex > -1 && e.RowIndex != dependenciesDataGridView.NewRowIndex)
				hasChanges = true;
		}

		private void dependenciesDataGridView_KeyUp(object sender, KeyEventArgs e)
		{
			if (e.KeyCode == Keys.Escape && dependenciesDataGridView.CurrentRow.IsNewRow)
				dependenciesDataGridView.CancelEdit();
		}

		private void dependenciesDataGridView_CellEnter(object sender, DataGridViewCellEventArgs e)
		{
			// HACK: This event handler is a workaround for an EditOnEnter bug that prevents rows from being selected when a header is clicked.
			// This code is based on the workaround found here: https://connect.microsoft.com/VisualStudio/feedback/Workaround.aspx?FeedbackID=98504
			// The MouseClick event handler for the grid is also used.

			dependenciesDataGridView.EditMode = DataGridViewEditMode.EditOnEnter;
		}

		private void dependenciesDataGridView_MouseClick(object sender, MouseEventArgs e)
		{
			// See the grid's CellEnter event handler for more information about the purpose of this handler.

			DataGridView.HitTestInfo hit = dependenciesDataGridView.HitTest(e.X, e.Y);

			if (hit.Type == DataGridViewHitTestType.RowHeader)
			{
				dependenciesDataGridView.EditMode = DataGridViewEditMode.EditOnKeystrokeOrF2;
				dependenciesDataGridView.EndEdit();
			}
		}

		private void dependenciesDataGridView_CellBeginEdit(object sender, DataGridViewCellCancelEventArgs e)
		{
			DataGridViewCell cell = dependenciesDataGridView[e.ColumnIndex, e.RowIndex];

			string value = cell.Value as string;

			if (!string.IsNullOrEmpty(value))
			{
				cell.Value = new SystemPath(project.Directory, value, true).CompletePath;
			}
		}

		private void dependenciesDataGridView_CellEndEdit(object sender, DataGridViewCellEventArgs e)
		{
			DataGridViewCell cell = dependenciesDataGridView[e.ColumnIndex, e.RowIndex];
			cell.ErrorText = null;

			string value = cell.Value as string;

			if (!string.IsNullOrEmpty(value) && System.IO.Path.IsPathRooted(value))
			{
				cell.Value = new SystemPath(value, true).CompleteRelativeTo(project.Directory);
			}
		}
		#endregion
	}
}